package core.process;

import core.process.pack.CodonPack;
import core.utils.EPara;
import core.utils.Utils;
import core.rb.PB;
import core.rb.r.PR;
import gui.processor.Processor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

/*Author: John Archer, Contact: john.archer.jpa@gmail.com*/
public class Codon{
    private PB pb;
    private Processor gp;
    private double filter;
    public Codon(PB pBlock, Processor gp, double filter){this.pb = pBlock;this.gp = gp;this.filter=filter;}
    public HashMap [] getCodon() throws Exception{
        int size = (int)((pb.getSize() / EPara.THREADS));
        int r = 0;
        ArrayList <PB> packs = new ArrayList();
        ArrayList <PR> pack;
        for(int x = 0; x<EPara.THREADS; x++){
            pack = new ArrayList();
            for(int y = 0; y<size; y++){ pack.add(pb.getRead(r++));}
            packs.add(new PB(pb.getRef(), pack));
        }
        PB fPack = packs.get(0);
        for(int x=r; x<pb.getSize(); x++){fPack.add(pb.getRead(r++));}
        CodonPack [] cp = new CodonPack[packs.size()];
        CountDownLatch cdl = new CountDownLatch(packs.size());
        for (int x = 0; x < packs.size(); x++) {
            if(x==0){cp[x] = new CodonPack(gp, cdl, packs.get(x), filter);}
            else{cp[x] = new CodonPack(null, cdl, packs.get(x), filter);}
        }
        cdl.await();
        HashMap <String, Integer> [] combined = new HashMap[pb.getRef().getDNA().length()-3];
        for(int x=0; x<combined.length;x++){combined[x] = new HashMap <String, Integer>();}
        for (int x = 0; x < cp.length; x++) {
            HashMap <String, Integer> [] packMaps = cp[x].getPOut();
            for(int site=0; site<packMaps.length-3;site++){
                HashMap <String, Integer> small = packMaps[site];
                Iterator iter = small.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry pairs = (Map.Entry)iter.next();
                    String codon = (String)pairs.getKey();
                    if(codon.indexOf("-")==-1){
                        int value = ((Integer)pairs.getValue()).intValue();
                        if(combined[site].containsKey(codon)){
                            int currVal = combined[site].get(codon).intValue();
                            currVal += value;
                            combined[site].remove(codon);
                            combined[site].put(codon, currVal);
                        }
                        else{combined[site].put(codon, value);}
                    }
                }
            }
        }
        HashMap <String, Integer> [] combinedSorted = new HashMap[pb.getRef().getDNA().length()-3];
        for(int x=0; x<combinedSorted.length;x++){combinedSorted[x] = new HashMap <String, Integer>();}
        for(int site=0; site<combined.length-3;site++){combinedSorted[site] = Utils.sortHashMap(combined[site]);}
        return combinedSorted;
    }
}